package org.lestr.secuel.sogl.maths;

import org.lestr.secuel.m3ds.IUsine;
import org.lestr.secuel.m3ds.maths.IPoint3d;
import org.lestr.secuel.m3ds.maths.IVecteur3d;

public class Vecteur3d extends Point3d<IPoint3d.IEcouteur<IVecteur3d>, IVecteur3d> implements IVecteur3d {


    // Déclaration de constantes
    private static final long serialVersionUID = 1L;


    /** Constructeur */
    public Vecteur3d(IUsine usine) {

        // Appel du constucteur hérité
        super(usine);

    }// FIN Constructeur


    /** Constructeur */
    public Vecteur3d(IUsine usine,
                     double x,
                     double y,
                     double z) {

        // Appel du constucteur hérité
        super(usine, x, y, z);

    }// FIN Constructeur


    /** Constructeur */
    public Vecteur3d(IUsine usine,
                     IVecteur3d point) {

        // Appel du constucteur hérité
        super(usine,
              point.obtenirX(),
              point.obtenirY(),
              point.obtenirZ());

    }// FIN Constructeur


    /** Retourne le norme du vecteur */
    @Override
    public double obtenirNorme() {

        return Math.sqrt(obtenirNormeAuCarré());

    }// FIN Méthode obtenirNorme


    /** Retourne le norme au carré du vecteur */
    @Override
    public double obtenirNormeAuCarré() {

        return obtenirX() * obtenirX()
               + obtenirY() * obtenirY()
               + obtenirZ() * obtenirZ();

    }// FIN Méthode obtenirNormeAuCarré


    /** Défini le vecteur comme le produit cartésien des deux vecteurs passés en paramètre. */
    @Override
    public void produitCartésien(IVecteur3d u,
                                 IVecteur3d v) {

        définirXYZ(u.obtenirY() * v.obtenirZ() - u.obtenirZ() * v.obtenirY(),
                   v.obtenirX() * u.obtenirZ() - v.obtenirZ() * u.obtenirX(),
                   u.obtenirX() * v.obtenirY() - u.obtenirY() * v.obtenirX());

    }// FIN Méthode produitCartésien


    /** Normalise le vecteur */
    @Override
    public void normaliser() {

        redimensionner(1.0 / obtenirNorme());

    }// FIN Méthode normaliser


    /** Retourne le produit vectoriel effectué entre le vecteur et un autre. */
    @Override
    public double produitVectoriel(IVecteur3d u) {

        return (obtenirX() * u.obtenirX()
                + obtenirY() * u.obtenirY()
                + obtenirZ() * u.obtenirZ());

    }// FIN Méthode produitVectoriel


    /** Retourne l'angle en degré effectué entre le vecteur et celui passé en paramètre. */
    @Override
    public double obtenirAngle(IVecteur3d u) {

        double x = this.produitVectoriel(u) / (this.obtenirNorme() * u.obtenirNorme());
        if (Double.isNaN(x))
            x = 0;
        double angle = Math.acos(x);
        return Math.toDegrees(angle);

    }// FIN Méthode obtenirAngle


    /** Multiplie le vecteur par une constante */
    @Override
    public void redimensionner(double d) {

        définirXYZ(d * obtenirX(),
                   d * obtenirY(),
                   d * obtenirZ());

    }// FIN Méthode redimensionner


    /** Additionne au vecteur un autre */
    @Override
    public void additionner(IVecteur3d u) {

        définirXYZ(obtenirX() + u.obtenirX(),
                   obtenirY() + u.obtenirY(),
                   obtenirZ() + u.obtenirZ());

    }// FIN Méthode additionner


    /** SOustrait au vecteur un autre */
    @Override
    public void soustraire(IVecteur3d u) {

        définirXYZ(obtenirX() - u.obtenirX(),
                   obtenirY() - u.obtenirY(),
                   obtenirZ() - u.obtenirZ());

    }// FIN Méthode soustraire


    @Override
    public IVecteur3d obtenirCopie() {

        return new Vecteur3d(obtenirUsine(), obtenirX(), obtenirY(), obtenirZ());

    }// FIN Méthode obtenirCopie


}// FIN Classe
